﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Furion.DependencyInjection;
using Microsoft.Extensions.Caching.Memory;

namespace YShop.Core.Managers.Caches
{
    public class CacheManager: ISingleton
    {
        /// <summary>
        /// 内存缓存
        /// </summary>
        private readonly IMemoryCache _memoryCache;
        private Dictionary<string, CacheItem> _cacheMap = new Dictionary<string, CacheItem>();
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="memoryCache"></param>

        public CacheManager(IMemoryCache memoryCache)
        {
            _memoryCache = memoryCache;
        }

        public TItem GetOrCreate<TItem>(string key, Func<ICacheEntry, TItem> factory)
        {
            if (!_cacheMap.ContainsKey(key))
                _cacheMap.Add(key, new CacheItem(factory));
            return _memoryCache.GetOrCreate(key, factory);
        }

        public Task<TItem> GetOrCreateAsync<TItem>(string key, Func<ICacheEntry, Task<TItem>> factory)
        {
            if (!_cacheMap.ContainsKey(key))
                _cacheMap.Add(key, new CacheItem(factory));
            return _memoryCache.GetOrCreateAsync(key, factory);
        }

        public TItem Get<TItem>(string key) 
        {
            return _memoryCache.Get<TItem>(key);
        }

        public TItem Set<TItem>(string key, TItem value)
        {
            if (!_cacheMap.ContainsKey(key))
                _cacheMap.Add(key, new CacheItem(value, 1));
            else
                _cacheMap[key] = new CacheItem(value, 1);
            return _memoryCache.Set(key,value);
        }

        public bool TryGetValue<TItem>(string key, out TItem value)
        {
            return _memoryCache.TryGetValue(key, out value);
        }

        public void Remove(params string[] keys)
        {
            foreach(var key in keys)
            {
                _memoryCache.Remove(key);
                _cacheMap.Remove(key);
            }
        }
        /// <summary>
        /// 清空缓存
        /// </summary>
        public void Clear()
        {
            foreach(var key in _cacheMap.Keys)
            {
                _cacheMap.Remove(key);
                _memoryCache.Remove(key);
            }
        }

        /// <summary>
        /// 更新缓存
        /// </summary>
        /// <param name="keys"></param>
        public List<dynamic> Update(params string [] keys)
        {
            var result = new List<dynamic>();
            foreach(var key in keys)
            {
                var item = _cacheMap[key];
                // 方法
                if(item.Type == 0)
                {
                    _memoryCache.Remove(key);
                    var func = (Func<ICacheEntry, dynamic>)item.Options;
                    result.Add(GetOrCreate(key, func));
                }
            }
            return result;
        }
    }

    internal class CacheItem
    {
        public object Options { get; set; }
        public int Type { get; set; }
        public CacheItem(object options,int type = 0)
        {
            Options = options;
            Type = type;
        }

        public CacheItem(Func<ICacheEntry, dynamic> func)
        {

        }
    }
}
